package day07

import day06.sparksql.Person
import org.apache.spark.SparkConf
import org.apache.spark.sql.{DataFrame, SparkSession}

object UDFDemo {
  def main(args: Array[String]): Unit = {
    /**
      * 自定义UDF：
      *   实现统计字符串的长度。使用sql语句，注册自定义UDF用spark.udf.register(。。。)
      */
    val conf: SparkConf = new SparkConf().setAppName("UDFDemo").setMaster("local[2]")
    val spark: SparkSession = SparkSession.builder().config(conf).getOrCreate()

    //模拟一个数据
    val names = List("tom","jerry","shuke")
    //使用map映射将names的每个数据都封装为样例类: names.map(x => PersonName(x))
    val namesDF: DataFrame = spark.createDataFrame(names.map(PersonName))//这个是上面的简写

    //将DF数据创建为临时视图
    namesDF.createOrReplaceTempView("t_person")

    // 注册自定义UDF：spark.udf.register（。。）
    // 第一个参数为自定义UDF的函数名。第二个参数就是函数实现内容，输入=>处理输出。
    // 如果该函数复杂的话可以创建一个类专们写该函数，定义好参数传参，然后在这里调用就行。
    spark.udf.register("fuhao_strlen", (name: String) => name.length)
    // 调用UDF进行查询，调用我们刚刚在上面注册的统计字符串长度的函数名
    // 在查询语句里面可以重命名返回结果的字段名，这个只是在修改我们创建的临时表的字段名，并不是修改DF或DS的字段名
    // 但是要注意DF和DS类型数据的字段名不能修改。严谨来说，DF和DS根本就没有所谓的字段名，字段名显示的是_1,_2这样的名
    val res: DataFrame = spark.sql("select name as new_name, fuhao_strlen(name) as nameLength from t_person")
    res.show()
    spark.stop()
  }
}
//样例类，封装数据
case class PersonName(name: String)
